import yaml
import json
import sys
import os
import getopt
import subprocess


def printUsage():
    print("Generate config.yaml for fabric sdk\nUsage:")
    print("    gen_sdk_configtx.py -o <orderer_num> -p <peer_num> -i <org_id>")
    print(
        "    or: gen_sdk_configtx.py --orderer_num=<orderer_num> --peer_num=<peer_num> --org_id=<org_id>"
    )


def parseArgs(argv):
    global orderer_num
    global peer_num
    global org_id
    opts, args = getopt.getopt(argv[1:], "ho:p:i:", ["help", "orderer_num=", "peer_num=", "org_id="])

    if len(opts) > 3 or len(args) != 0:
        print("Invalid paramater")
        sys.exit()
    for opt, arg in opts:
        if opt in ("-o", "--orderer_num"):
            orderer_num = int(arg)
        elif opt in ("-p", "--peer_num"):
            peer_num = int(arg)
        elif opt in ("-i", "--org_id"):
            org_id = int(arg)
        else:
            printUsage()
            sys.exit()


def gen_config():
    config = {
        "version": 2,
        "client": {
            "organization": f"Org{org_id}",
            "logging": {"level": "info"},
            "cryptoconfig": {"path": "../crypto-config"},
            "credentialStore": {
                "path": "/dev/shm/state-store",
                "cryptoStore": {"path": "/dev/shm/msp"},
            },
            "BCCSP": {
                "security": {
                    "enabled": True,
                    "default": {"provider": "SW"},
                    "hashAlgorithm": "SHA2",
                    "softVerify": True,
                    "level": 256,
                }
            },
            "tlsCerts": {
                "systemCertPool": True,
                "client": {
                    "key": {
                        "path": f"../crypto-config/peerOrganizations/org{org_id}.demo.com/users/User1@org{org_id}.demo.com/tls/client.key"
                    },
                    "cert": {
                        "path": f"../crypto-config/peerOrganizations/org{org_id}.demo.com/users/User1@org{org_id}.demo.com/tls/client.crt"
                    },
                },
            },
        },
        "channels": {
            "mychannel": {
                "peers": {},
                "policies": {
                    "queryChannelConfig": {
                        "minResponses": 1,
                        "maxTargets": 1,
                        "retryOpts": {
                            "attempts": 5,
                            "initialBackoff": "1s",
                            "maxBackoff": "5s",
                            "backoffFactor": 2.0,
                        },
                    }
                },
            }
        },
        "organizations": {},
        "ordererorg": {
            "mspID": "OrdererMSP",
            "cryptoPath": "../crypto-config/ordererOrganizations/demo.com/users/{username}@demo.com/msp",
        },
        "orderers": {},
        "peers": {},
    }
    for i in range(1, org_num + 1):
        org_name = f"org{i}"
        org_config = {
            "mspid": f"Org{i}MSP",
            "cryptoPath": f"../crypto-config/peerOrganizations/{org_name}.demo.com/users/{{username}}@{org_name}.demo.com/msp",
            "peers": [f"peer0.{org_name}.demo.com"],
        }
        config["organizations"][org_name] = org_config

    for i in range(1, orderer_num + 1):
        orderer_name = f"orderer{i}.demo.com"
        orderer_port = orderer_start_port + i - 1
        orderer_config = {
            "url": f"grpcs://{FABRIC_ORDERER_IPs[i-1]}:{orderer_port}",
            "grpcOptions": {
                "ssl-target-name-override": orderer_name,
                "keep-alive-time": "0s",
                "keep-alive-timeout": "20s",
                "keep-alive-permit": False,
                "fail-fast": False,
                "allow-insecure": False,
            },
            "tlsCACerts": {
                "path": f"../crypto-config/ordererOrganizations/demo.com/tlsca/tlsca.demo.com-cert.pem"
            },
        }
        config["orderers"][orderer_name] = orderer_config

    for i in range(1, org_num + 1):
        org_name = f"org{i}"
        peer_name = f"peer0.{org_name}.demo.com"
        peer_port = peer_start_port + i
        peer_config = {
            "url": f"grpcs://{FABRIC_PEER_IPs[i-1]}:{peer_port}",
            "grpcOptions": {
                "ssl-target-name-override": peer_name,
                "keep-alive-time": "0s",
                "keep-alive-timeout": "20s",
                "keep-alive-permit": False,
                "fail-fast": False,
                "allow-insecure": False,
            },
            "tlsCACerts": {
                "path": f"../crypto-config/peerOrganizations/{org_name}.demo.com/tlsca/tlsca.{org_name}.demo.com-cert.pem"
            },
        }
        config["peers"][peer_name] = peer_config
        config["channels"]["mychannel"]["peers"][peer_name] = {
            "endorsingPeer": True,
            "chaincodeQuery": True,
            "ledgerQuery": True,
            "eventSource": True,
        }

    yaml_data = yaml.dump(
        config, default_flow_style=False, allow_unicode=True, sort_keys=False
    )

    with open(f"{current_folder}/sdk-config-{org_id}.yaml", "w") as file:
        file.write(yaml_data)


def get_array_from_conf_file(file_path, variable_name):
    # 创建一个新的Shell进程并在其中运行配置文件
    process = subprocess.Popen(
        [
            "bash",
            "-c",
            f"source {file_path}" + "&& echo -n ${" + f"{variable_name}" + "[@]}",
        ],
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
    )

    # 读取进程的输出并解析为环境变量
    output, error = process.communicate()
    env_vars = output.decode("utf-8").split(" ")

    return env_vars


org_id = 1
org_num = 4
orderer_num = 1
peer_start_port = 7100
orderer_start_port = 7050

# 运行配置文件并获取环境变量
current_folder = os.path.dirname(os.path.abspath(__file__))
FABRIC_PEER_IPs = get_array_from_conf_file(
    f"{current_folder}/../../../cluster_IP.conf", "FABRIC_PEER_IPs"
)
FABRIC_ORDERER_IPs = get_array_from_conf_file(
    f"{current_folder}/../../../cluster_IP.conf", "FABRIC_ORDERER_IPs"
)


if __name__ == "__main__":
    parseArgs(sys.argv)

    gen_config()
